package com.college.authority.service.impl;

import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.college.authority.mapper.TRoleActionMapper;
import com.college.authority.mapper.UmsMenuMapper;
import com.college.authority.mapper.UmsResourceMapper;
import com.college.authority.mapper.UmsRoleMapper;
import com.college.authority.service.*;
import com.college.common.pojo.ao.*;
import com.college.common.pojo.dto.umsRole.TRoleActionModuleDto;
import com.college.common.pojo.dto.umsRole.UmsRoleDto;
import com.college.common.pojo.vo.umsRole.GetUmsRoleByUmsAdminIdsVO;
import com.college.common.utils.list.ListUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 后台角色管理Service实现类
 * Created by macro on 2018/9/30.
 */
@Service
public class UmsRoleServiceImpl extends ServiceImpl<UmsRoleMapper, UmsRole> implements UmsRoleService {
	// @Autowired
	// private UmsAdminCacheService adminCacheService;

	@Autowired
	private UmsAdminRoleRelationService roleRelationService;
	@Autowired
	private UmsRoleMenuRelationService roleMenuRelationService;
	@Autowired
	private UmsRoleResourceRelationService roleResourceRelationService;
	@Autowired
	private TRoleActionModuleService tRoleActionModuleService;
	@Autowired
	private TRoleActionMapper tRoleActionMapper;
	@Autowired
	private UmsMenuMapper menuMapper;
	@Autowired
	private UmsResourceMapper resourceMapper;
	@Autowired
	private TRoleActionRelationService tRoleActionRelationService;

	@Autowired
	private UmsRoleMapper umsRoleMapper;

	@Override
	public boolean create(UmsRoleDto role) {
		role.setCreateTime(new Date());
		role.setAdminCount(0);
		role.setSort(0);
		boolean flag = save(role);
		if (flag) {
			// 关联添加的菜单和资源
			allocMenu(role.getId(), role.getMenus());
			allocResource(role.getId(), role.getResources());
			allocPermissions(role.getId(), role.getPermissions().stream().map(action -> Long.parseLong(action.toString())).collect(Collectors.toList()));
		}
		return flag;
	}

	@Override
	public boolean delete(List<Long> ids) {
		for (Long roleId : ids) {
			//   删除角色菜单关联
			roleMenuRelationService.lambdaUpdate().eq(UmsRoleMenuRelation::getRoleId, roleId).remove();
			//  删除资源角色关联
			roleResourceRelationService.lambdaUpdate().eq(UmsRoleResourceRelation::getRoleId, roleId).remove();
			//  删除用户角色关联
			roleRelationService.lambdaUpdate().eq(UmsAdminRoleRelation::getRoleId, roleId).remove();
		}
		boolean success = removeByIds(ids);
		// adminCacheService.delResourceListByRoleIds(ids);
		return success;
	}

	@Override
	public Page<UmsRoleDto> list(String keyword, Integer pageSize, Integer pageNum) {
		Page<UmsRole> page = new Page<>(pageNum, pageSize);
		QueryWrapper<UmsRole> wrapper = new QueryWrapper<>();
		LambdaQueryWrapper<UmsRole> lambda = wrapper.lambda();
		if (CharSequenceUtil.isNotEmpty(keyword)) {
			lambda.like(UmsRole::getName, keyword);
		}
		Page<UmsRoleDto> pageDto = new Page<>(pageNum, pageSize);
		BeanUtils.copyProperties(page(page, wrapper), pageDto);
		pageDto.setRecords(page.getRecords().stream().map(role -> {
			UmsRoleDto umsRoleDto = new UmsRoleDto();
			BeanUtils.copyProperties(role, umsRoleDto);
			// 获取角色的所拥有的菜单项
			umsRoleDto.setMenus(roleMenuRelationService.lambdaQuery()
					.select(UmsRoleMenuRelation::getMenuId)
					.eq(UmsRoleMenuRelation::getRoleId, umsRoleDto.getId())
					.list().stream().map(UmsRoleMenuRelation::getMenuId)
					.collect(Collectors.toList()));
			// 获取角色所拥有的资源
			umsRoleDto.setResources(roleResourceRelationService.lambdaQuery()
					.select(UmsRoleResourceRelation::getResourceId)
					.eq(UmsRoleResourceRelation::getRoleId, umsRoleDto.getId())
					.list().stream().map(UmsRoleResourceRelation::getResourceId).collect(Collectors.toList()));
			// 获取角色所拥有的行为权限
			umsRoleDto.setPermissions(this.listActions(umsRoleDto.getId()));
			return umsRoleDto;
		}).collect(Collectors.toList()));
		return pageDto;
	}

	@Override
	public List<UmsMenu> getMenuList(Long adminId) {
		return menuMapper.getMenuList(adminId);
	}

	@Override
	public List<UmsMenu> listMenu(Long roleId) {
		return menuMapper.getMenuListByRoleId(roleId);
	}

	@Override
	public List<UmsResource> listResource(Long roleId) {
		return resourceMapper.getResourceListByRoleId(roleId);
	}

	@Override
	public List<TRoleActionModuleDto> listActions(Long roleId) {
		// 通过角色找到所有的具体操作行为根据父模块进行分组
		List<TRoleAction> actionList = tRoleActionMapper.getActionListByRoleId(roleId);
		List<TRoleActionModule> permission = tRoleActionModuleService.lambdaQuery().list();
		return permission.stream().map(item -> {
			TRoleActionModuleDto tRoleActionModuleDto = new TRoleActionModuleDto();
			// 找出属于该模块的权限行为
			List<TRoleAction> collect = actionList.stream()
					.filter(tRoleAction -> tRoleAction.getModuleId().equals(item.getPermissionId()))
					.collect(Collectors.toList());
			BeanUtils.copyProperties(item, tRoleActionModuleDto);
			tRoleActionModuleDto.setActionList(collect);
			return tRoleActionModuleDto;
		}).collect(Collectors.toList());
	}

	@Override
	public Map<Long, List<TRoleActionModuleDto>> listActionsByIds(List<Long> ids) {
		List<TRoleActionAndRid> actionList = ListUtils.filterEmpty(tRoleActionMapper.getActionListByRoleIds(ids));
		Map<String, List<TRoleActionAndRid>> stringListMap = actionList.stream().collect(Collectors.groupingBy(TRoleActionAndRid::getRid));
		List<TRoleActionModule> permission = tRoleActionModuleService.lambdaQuery().list();
		Map<Long, List<TRoleActionModuleDto>> longListHashMap = new HashMap<>();
		for (Map.Entry<String, List<TRoleActionAndRid>> stringListEntry : stringListMap.entrySet()) {
			List<TRoleActionModuleDto> tRoleActionModules = permission.stream().map(item -> {
				TRoleActionModuleDto tRoleActionModuleDto = new TRoleActionModuleDto();
				// 找出属于该模块的权限行为
				List<TRoleAction> collect = stringListEntry.getValue().stream()
						.filter(tRoleAction -> tRoleAction.getModuleId().equals(item.getPermissionId()))
						.collect(Collectors.toList());
				BeanUtils.copyProperties(item, tRoleActionModuleDto);
				tRoleActionModuleDto.setActionList(collect);
				return tRoleActionModuleDto;
			}).collect(Collectors.toList());
			// key:角色 value:角色所属权限行为
			longListHashMap.put(Long.valueOf(stringListEntry.getKey()), tRoleActionModules);
		}
		return longListHashMap;
	}

	@Override
	public int allocMenu(Long roleId, List<Long> menuIds) {
		//先删除原有关系
		QueryWrapper<UmsRoleMenuRelation> wrapper = new QueryWrapper<>();
		wrapper.lambda().eq(UmsRoleMenuRelation::getRoleId, roleId);
		roleMenuRelationService.remove(wrapper);
		//批量插入新关系
		List<UmsRoleMenuRelation> relationList = new ArrayList<>();
		for (Long menuId : menuIds) {
			UmsRoleMenuRelation relation = new UmsRoleMenuRelation();
			relation.setRoleId(roleId);
			relation.setMenuId(menuId);
			relationList.add(relation);
		}
		roleMenuRelationService.saveBatch(relationList);
		return menuIds.size();
	}

	@Override
	public int allocResource(Long roleId, List<Long> resourceIds) {
		//先删除原有关系
		QueryWrapper<UmsRoleResourceRelation> wrapper = new QueryWrapper<>();
		wrapper.lambda().eq(UmsRoleResourceRelation::getRoleId, roleId);
		roleResourceRelationService.remove(wrapper);
		//批量插入新关系
		List<UmsRoleResourceRelation> relationList = new ArrayList<>();
		for (Long resourceId : resourceIds) {
			UmsRoleResourceRelation relation = new UmsRoleResourceRelation();
			relation.setRoleId(roleId);
			relation.setResourceId(resourceId);
			relationList.add(relation);
		}
		roleResourceRelationService.saveBatch(relationList);
		// adminCacheService.delResourceListByRole(roleId);
		return resourceIds.size();
	}

	@Override
	public boolean allocPermissions(Long roleId, List<Long> actionIds) {
		// 先删除原有的关联角色的所有行为
		tRoleActionRelationService.lambdaUpdate().eq(TRoleActionRelation::getRid, roleId).remove();
		List<TRoleActionRelation> tRoleActionRelations = new ArrayList<>();
		actionIds.forEach((actionId) -> {
			TRoleActionRelation tRoleActionRelation = new TRoleActionRelation();
			tRoleActionRelation.setAid(actionId);
			tRoleActionRelation.setRid(roleId);
			tRoleActionRelations.add(tRoleActionRelation);
		});
		return tRoleActionRelationService.saveBatch(tRoleActionRelations);
	}

	@Override
	public boolean updateRole(UmsRoleDto role) {
		UmsRole umsRole = new UmsRole();
		BeanUtils.copyProperties(role, umsRole);
		allocResource(role.getId(), role.getResources());
		allocMenu(role.getId(), role.getMenus());
		allocPermissions(role.getId(), role.getPermissions().stream().map(action -> Long.parseLong(action.toString())).collect(Collectors.toList()));
		return updateById(umsRole);
	}

	@Override
	public List<GetUmsRoleByUmsAdminIdsVO> getUmsRoleByUmsAdminIds(List<Long> umsAdminIds) {
		return ListUtils.filterEmpty(umsRoleMapper.getUmsRoleByUmsAdminIds(umsAdminIds));
	}
}
